#include "StdAfx.h"
#include "EtchChecker.h"
#include "MeasureStation.h"
#include "Measure.h"


CEtchChecker::CEtchChecker(void)
{
  Init();
}

CEtchChecker::CEtchChecker(const tstring& checkerName)
  : name_(checkerName)
{
  Init();
}

CEtchChecker::~CEtchChecker(void)
{
}

void CEtchChecker::Init(void)
{
  ok_         = FALSE;
  check_type_ = 0;

  etch_min_gray_            = 0;
  etch_max_gray_            = 0;
  etch_area_threshold_      = 1;
  background_min_gray_      = 0;
  background_max_gray_      = 0;
  background_noise_radius_  = 1;

  roi_components_.clear();
  roi_operators_.clear();

  angle_box_2 ab2(0, 0, 15, 15, 0);
  roi_components_.push_back(ab2);
  roi_operators_.push_back(0);
}

void CEtchChecker::Reset(void)
{
  ok_ = false;
}

long CEtchChecker::Check(const CCoordSys& cs)
{
  Halcon::Hobject roiRgn;
  GenerateRoi(&roiRgn, cs);

  Halcon::Hobject reducedImage;
  Halcon::reduce_domain(theImage, roiRgn, &reducedImage);

  Halcon::Hobject bknRgn;
  Halcon::threshold(reducedImage, &bknRgn, BackgroundMinGray(), BackgroundMaxGray());
  Halcon::connection(bknRgn, &bknRgn);
  Halcon::select_shape_std(bknRgn, &bknRgn, "max_area", 0);
  Halcon::closing_circle(bknRgn, &bknRgn, BackgroundNoiseRadius()+0.5);
  Halcon::fill_up(bknRgn, &bknRgn);

  Halcon::Hobject etchRgn, etchRgns;
  Halcon::reduce_domain(theImage, bknRgn, &reducedImage);
  Halcon::threshold(reducedImage, &etchRgn, EtchMinGray(), EtchMaxGray());
  Halcon::connection(etchRgn, &etchRgns);
  Halcon::select_shape(etchRgns, &etchRgns, "area", "and", EtchAreaThreshold(), 1e6);

  Hlong numEtchs = 0;
  Halcon::count_obj(etchRgns, &numEtchs);
  if (numEtchs>0) {
    ok_ = false;
  } else {
    ok_ = true;
  }

  Halcon::set_color(hHalconWnd, "red");
  Halcon::set_draw(hHalconWnd, "fill");
  Halcon::disp_obj(etchRgns, hHalconWnd);

  return CErrorCode::kOk;
}

void CEtchChecker::roi_add(const shape_2& shape2, int opt)
{
  roi_components_.push_back(shape2);
  roi_operators_.push_back(opt);
}

void CEtchChecker::roi_clear(void)
{
  roi_components_.clear();
  roi_operators_.clear();
}

void CEtchChecker::roi_backup(void)
{
  roi_components_back_  = roi_components_;
  roi_operators_back_   = roi_operators_;
}

void CEtchChecker::roi_restore(void)
{
  roi_components_ = roi_components_back_;
  roi_operators_  = roi_operators_back_;
}

void CEtchChecker::GenerateRoi(Halcon::Hobject *roiRgn, const CCoordSys& cs)
{
  CMeasureStation *ms = theApp.project().FindStation(station_);
  ASSERT(ms!=NULL);

  Halcon::Hobject tmpRgn;
  Halcon::gen_empty_region(roiRgn);
  GenRgnVisitor grv(tmpRgn, cs);

  for (std::vector<shape_2>::size_type n=0; n<roi_components_.size(); ++n) {
    boost::apply_visitor(grv, roi_components_[n]);
    switch (roi_operators_[n])
    {
    case kSetUnion:
      Halcon::union2(*roiRgn, tmpRgn, roiRgn);
      break;

    case kSetIntersection:
      Halcon::intersection(*roiRgn, tmpRgn, roiRgn);
      break;

    case kSetDifference:
      Halcon::difference(*roiRgn, tmpRgn, roiRgn);
      break;

    case kSetSymmetricDifference:
      Halcon::symm_difference(*roiRgn, tmpRgn, roiRgn);
      break;

    default:
      break;
    }
  }
}

void CEtchChecker::ChangeCoordSys(const CCoordSys& ocs, const CCoordSys& ncs)
{
  ChangeCSVisitor ccsv(ocs, ncs);
  for (std::vector<shape_2>::size_type n=0; n<roi_components_.size(); ++n) {
    boost::apply_visitor(ccsv, roi_components_[n]);
  }
}